package com.ddz.shortcut

import android.accessibilityservice.AccessibilityService
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import com.ddz.shortcut.utils.ExeHelper
import com.ddz.shortcut.utils.JKShortcutLog
import com.ddz.shortcut.utils.JKTextUtils

class JKShortcutCoreImpl(var context: AccessibilityService) : JKShortcutCore {
    var disposedModules = arrayListOf<JKDisposedModule>()
    var currentName: String? = null
    var currentPackage: String? = null

    //在同一个页面最多执行点击次数
    private var _sameNameExeMaxCount = -1
    private var lastEventTimeMillis = 0L
    private var _eventWaitIntervalsMillis = 0L
    private var lastClickTimeMillis = 0L
    private var _clickIntervalTimeMillis = 0L
    private var _listener: JKShortcutListener? = null
    private var _clickCount = 0

    //如果递归找到了的话要通过这个参数退出递归
    private var _recursionFind = false

    //最大遍历树层次
    private var _maxRecursionTreeLayer = -1

    override fun loadDisposedModule(modules: ArrayList<JKDisposedModule>) {
        this.disposedModules.clear()
        this.disposedModules.addAll(modules)
    }

    override fun setListener(listener: JKShortcutListener) {
        this._listener = listener
    }

    override fun setEventIntervalTimeMillis(interval: Long) {
        this._eventWaitIntervalsMillis = interval
    }

    override fun setClickIntervalTimeMillis(interval: Long) {
        this._clickIntervalTimeMillis = interval
    }

    override fun setSameNameExeMaxCount(count: Int) {
        this._sameNameExeMaxCount = count
    }

    override fun setMaxRecursionTreeLayer(layer: Int) {
        this._maxRecursionTreeLayer = layer
    }

    override fun event(event: AccessibilityEvent?) {
        val currentTimeMillis = System.currentTimeMillis()
        if (currentTimeMillis - lastClickTimeMillis < _clickIntervalTimeMillis) {
            return
        }
        if (currentTimeMillis - lastEventTimeMillis < _eventWaitIntervalsMillis) {
            return
        }
        lastEventTimeMillis = currentTimeMillis
        try {
            JKShortcutLog.v("捷径") { "开始${event?.eventType}" }
            val windowInfo = context.rootInActiveWindow ?: return
            JKShortcutLog.v("捷径") { "开始解析" }
            if (event != null && (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED)) {
                currentPackage = event.packageName?.toString()
                val newClassName = event.className?.toString() ?: windowInfo.className?.toString()
                if (currentName != newClassName) {
                    currentName = newClassName
                    _clickCount = 0
                }
                JKShortcutLog.v("捷径") { "页面改变${currentName}" }
            }
            JKShortcutLog.v("捷径") { "同一个页面处理次数${_clickCount}" }
            if (_sameNameExeMaxCount != -1 && _clickCount >= _sameNameExeMaxCount) {
                return
            }
            if (event?.source != null) {
                val hasNeedDisposed = hasNeedDisposed(event.source, disposedModules)
                if (hasNeedDisposed?.disposedModule != null) {
                    disposed(event.source, hasNeedDisposed.disposedModule!!)
                    JKShortcutLog.v("捷径") { "触发的事件直接可以处理" }
                    return
                }
            }
            JKShortcutLog.v("捷径") { "开始遍历" }
            _recursionFind = false
            recursionView(windowInfo){ viewInfo, disposedModule ->
                disposed(viewInfo, disposedModule)
            }
//            recursionView(windowInfo, 0) { viewInfo, disposedModule ->
//                disposed(viewInfo, disposedModule)
//            }
        } catch (e: Exception) {
            e.printStackTrace()
            _listener?.onError(e)
        }
    }


    var foreachLayer = 0

    //While循环实现
    fun recursionView(
        windowInfo: AccessibilityNodeInfo,
        callback: (viewInfo: AccessibilityNodeInfo, disposedModule: JKDisposedModule) -> Unit
    ) {
        foreachLayer = 0
        var currentLayerNodes: ArrayList<AccessibilityNodeInfo?>? = arrayListOf(windowInfo)
        while (currentLayerNodes?.size ?: 0 > 0) {
            if (_maxRecursionTreeLayer != -1 && foreachLayer >= _maxRecursionTreeLayer) {
                return
            }
            var tempChildNodes: ArrayList<AccessibilityNodeInfo?>? = null
            for (index in 0 until (currentLayerNodes?.size ?: 0)) {
                val childNode = currentLayerNodes?.getOrNull(index) ?: continue
                if (!childNode.isVisibleToUser) continue
                JKShortcutLog.v(
                    "捷径"
                ) { "遍历层级：${foreachLayer} id:${childNode.viewIdResourceName} text:${childNode.text} name:${childNode.className}" }
                val hasNeedDisposed = hasNeedDisposed(childNode, disposedModules)
                if (hasNeedDisposed?.disposedModule != null) {
                    callback(childNode, hasNeedDisposed.disposedModule!!)
//            windowInfo.recycle()
                    JKShortcutLog.v("捷径") { "识别到广告的层级：${foreachLayer}" }
                    return
                }
                if (hasNeedDisposed?.skipRecursion == true) {
                    continue
                }
                if (childNode.childCount > 0 && (_maxRecursionTreeLayer == -1 || (_maxRecursionTreeLayer != -1 && foreachLayer >= _maxRecursionTreeLayer))) {
                    if (tempChildNodes == null) {
                        tempChildNodes = arrayListOf()
                    }
                    JKShortcutLog.v("捷径") { "子层级大小：${childNode.childCount}" }
                    for (grandsonNodeIndex in 0 until childNode.childCount) {
                        val grandsonNode = childNode.getChild(grandsonNodeIndex)
                        tempChildNodes.add(grandsonNode)
                    }
                }
            }
            currentLayerNodes = tempChildNodes
            foreachLayer += 1
        }
        JKShortcutLog.v("捷径") { "最大层级${foreachLayer}" }
    }

    //递归实现
    fun recursionView(
        windowInfo: AccessibilityNodeInfo,
        layer: Int,
        callback: (viewInfo: AccessibilityNodeInfo, disposedModule: JKDisposedModule) -> Unit
    ) {
        if (_recursionFind) {
            return
        }
        if (_maxRecursionTreeLayer != -1 && layer >= _maxRecursionTreeLayer) {
            return
        }
        JKShortcutLog.v(
            "捷径"
        ) { "遍历层级${layer} id:${windowInfo.viewIdResourceName} text:${windowInfo.text} name:${windowInfo.className}" }
        if (!windowInfo.isVisibleToUser) return
        val hasNeedDisposed = hasNeedDisposed(windowInfo, disposedModules)
        if (hasNeedDisposed?.disposedModule != null) {
            callback(windowInfo, hasNeedDisposed.disposedModule!!)
            _recursionFind = true
//            windowInfo.recycle()
            return
        }
        if (hasNeedDisposed?.skipRecursion == true) {
            return
        }
        if (windowInfo.childCount > 0) {
            for (index in 0 until windowInfo.childCount) {
                val child = windowInfo.getChild(index) ?: return
                recursionView(child, layer + 1, callback)
                if (_recursionFind) {
                    return
                }
            }
        } else {
            JKShortcutLog.v("捷径") { "最大层级${layer}" }
        }
        return
    }

    override fun hasNeedDisposed(
        viewInfo: AccessibilityNodeInfo,
        disposedModule: ArrayList<JKDisposedModule>,
    ): HasNeedDisposed? {
        for (module in disposedModule) {
            val hasNeedDisposed = hasNeedDisposed(viewInfo, module) ?: continue
            when {
                hasNeedDisposed.disposedModule != null -> {
                    return hasNeedDisposed
                }
                hasNeedDisposed.skipRecursion -> {
                    return hasNeedDisposed
                }
            }
        }
        return null
    }

    override fun hasNeedDisposed(
        viewInfo: AccessibilityNodeInfo,
        disposedSingleModule: JKDisposedModule,
    ): HasNeedDisposed? {
        when {
            //如果ClassName过滤规则匹配上了的话要停止往下遍历（比如ListView的情况肯定是不行的，EditView也不行...）
            !disposedSingleModule.classNameFilterRegex.isNullOrBlank() && JKTextUtils.match(
                disposedSingleModule.classNameFilterRegex,
                viewInfo.className
            ) -> {
                return HasNeedDisposed(null, true)
            }
            //如果不是同一个源的话不需要处理
            !disposedSingleModule.matchClassName.isNullOrBlank() && !disposedSingleModule.matchClassName.equals(
                currentName
            ) -> return HasNeedDisposed(null, true)
        }
        val isMatch = when (disposedSingleModule.matchType) {
            JKShortcut.MATCH_ID -> {
                JKTextUtils.match(disposedSingleModule.matchRegex, viewInfo.viewIdResourceName)
            }
            JKShortcut.MATCH_TEXT -> {
                JKTextUtils.match(disposedSingleModule.matchRegex, viewInfo.text)
            }
            else -> {
                false
            }
        }
        return if (isMatch) {
            _listener?.onDisposedState(
                JKShortcut.DISPOSED_STATE_START,
                viewInfo,
                disposedSingleModule
            )
            disposedSingleModule toHasNeedDisposed false
        } else {
            null
        }
    }

    override fun disposed(viewInfo: AccessibilityNodeInfo, disposedSingleModule: JKDisposedModule) {
        when (disposedSingleModule.exeType) {
            JKShortcut.EXE_TYPE_CLICK -> {
                JKShortcutLog.v("捷径") { "事件处理$viewInfo" }
                lastClickTimeMillis = System.currentTimeMillis()
                _clickCount++
                ExeHelper.click(context, viewInfo)
                _listener?.onDisposedState(
                    JKShortcut.DISPOSED_STATE_SUCCESS,
                    viewInfo,
                    disposedSingleModule
                )
            }
        }
    }
}